﻿using System;
using System.Collections.Generic;

namespace ProblemsSet
{
    public class Problem_68 : BaseProblem
    {
        public override object GetResult()
        {
            const int val = 10;
            const int items = 15;
            const int maxDigits = 16;
            const int min = 8;
            const int max = 20;

            //const int val = 6;
            //const int items = 9;
            //const int maxDigits = 9;
            //const int min = 9;
            //const int max = 12;


            var hs = new HashSet<byte>();
            for (var i = 1; i <= val; i++)
            {
                hs.Add((byte)i);
            }
            var result = new List<string>();
            var current = new byte[items];
            for (var i = min; i <= max; i++)
            {
                FormeSets(ref result, hs, current, 0, i);
            }
            
            var result2 = new List<string>();
            foreach (var s in result)
            {
                var tmp = GetStringByString(s);
                if (tmp.Length != maxDigits) continue;
                result2.Add(tmp);
            }
            result2.Sort();

            return result2[result2.Count-1];
        }

        private static void FormeSets(ref List<string> result, HashSet<byte> leaved, byte[] current, int index, int summ)
        {
            if (index >= current.Length)
            {
                result.Add(GetStringByBytes(current));
                return;
            }
            foreach (var b in leaved)
            {
                var tmp = new HashSet<byte>(leaved);
                tmp.Remove(b);
                var tmpb = new List<byte>(current).ToArray();
                tmpb[index] = b;

                if (index <current.Length-1 &&  index % 3 == 2)
                {
                    tmpb[index + 2] = b;
                } else if (index == 1)
                {
                    tmpb[current.Length - 1] = b;
                }else if (index == current.Length-1)
                {
                    tmpb[1] = b;
                }else if (index > 2 && index % 3 == 1)
                {
                    tmpb[index - 2] = b;
                }
                if (!IsGet(tmpb, summ)) continue;
                var next = index+1;
                while (next < current.Length)
                {
                    if (current[next] == 0) break;
                        next++;
                }
                FormeSets(ref result, tmp, tmpb, next, summ);
            }
        }

        private static bool IsGet(byte[] value, int sum)
        {
            if (value[0] != 0)
            {
                for (var i = 1; i < value.Length / 3; i++)
                {
                    if (value[3*i] != 0 && value[3*i] < value[0]) return false;
                }
            }
            

            for (var i = 0; i < value.Length/3; i++)
            {
                var sm = 0;
                bool ex = false;
                for (var j = 0; j < 3; j++)
                {
                    var val = value[i*3 + j];
                    sm += val;
                    if (val == 0 ) ex = true;
                }
                if (sm > sum)
                    return false;
                if (ex && sm == sum)
                    return false;
                if (!ex && sm != sum)
                    return false;
            }
            return true;
        }

        private static string GetStringByBytes(byte[] val)
        {
            var res = "";
            for (var i = 0; i < val.Length; i++)
            {
                res += Convert.ToChar(val[i]+64);
            }
            return res;
        }

        private static string GetStringByString(string val)
        {
            var res = "";
            for (var i = 0; i < val.Length; i++)
            {
                res += (Convert.ToByte(val[i])-64);
            }
            return res;
        }

        public override string Problem
        {
            get
            {
                return @"Consider the following 'magic' 3-gon ring, filled with the numbers 1 to 6, and each line adding to nine.


Working clockwise, and starting from the group of three with the numerically lowest external node (4,3,2 in this example), each solution can be described uniquely. For example, the above solution can be described by the set: 4,3,2; 6,2,1; 5,1,3.

It is possible to complete the ring with four different totals: 9, 10, 11, and 12. There are eight solutions in total.

Total	Solution Set
9	4,2,3; 5,3,1; 6,1,2
9	4,3,2; 6,2,1; 5,1,3
10	2,3,5; 4,5,1; 6,1,3
10	2,5,3; 6,3,1; 4,1,5
11	1,4,6; 3,6,2; 5,2,4
11	1,6,4; 5,4,2; 3,2,6
12	1,5,6; 2,6,4; 3,4,5
12	1,6,5; 3,5,4; 2,4,6
By concatenating each group it is possible to form 9-digit strings; the maximum string for a 3-gon ring is 432621513.

Using the numbers 1 to 10, and depending on arrangements, it is possible to form 16- and 17-digit strings. What is the maximum 16-digit string for a 'magic' 5-gon ring?

";
            }
        }

        public override bool IsSolved
        {
            get
            {
                return true;
            }
        }

        public override object Answer
        {
            get
            {
                return "6531031914842725";
            }
        }

    }
}
